﻿#include <libdaq/backend/tcp_server/tcp_server.h>
#include <libdaq/backend/usb_server/usb_server.h>

#include "libdaq/device/DAQ125/DAQ125.h"
#include "libdaq/device/DAQ206/DAQ206.h"
#include "libdaq/device/DAQ207/DAQ207.h"
#include "libdaq/device/DAQ216/DAQ216.h"
#include "libdaq/device/DAQ217/DAQ217.h"

#include "once_trigger_thread/once_trigger_thread.h"

#include <thread>
#include <iostream>

#ifdef WIN32
#pragma comment(linker, "/subsystem:console /ENTRY:mainCRTStartup")
#endif

int main(int argc, char *argv[])
{
    std::unique_ptr<libdaq::backend::LockzhinerTCPServer> tcp_server_; // TCP服务器

    // FIXME:在此根据您的设备类型创建对应的设备实例
    std::shared_ptr<libdaq::device::DAQ207> base_device_
        = std::make_shared<libdaq::device::DAQ207>(); // 设备指针

    // 创建TCP服务器
    std::string ip_address = "192.168.1.100";
    uint16_t port = 8899;
    tcp_server_ = std::make_unique<libdaq::backend::LockzhinerTCPServer>(ip_address, port);

    // 1.开始扫描TCP设备
    std::cout << "开始扫描TCP设备..." << std::endl;
    int connect_count = 1; // 连接数量
    tcp_server_->StartAccept(10000, true, connect_count);
    
    // 等待连接完成
    while (!tcp_server_->IsAcceptComplete()) {
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
    }

    // 获取连接的客户端IP列表
    auto ip_list = tcp_server_->GetClientsIP();
    if (ip_list.empty()) {
        std::cout << "未找到TCP设备连接，请检查网络连接" << std::endl;
        return -1;
    }

    // 使用第一个连接的设备
    std::string client_ip = ip_list[0];
    std::cout << "找到TCP设备: " << client_ip << std::endl;

    auto socket = tcp_server_->GetClient(client_ip);
    if (socket == nullptr) {
        std::cout << "获取TCP客户端失败" << std::endl;
        return -1;
    }

    base_device_->UseBackend(socket);

    // 2.初始化设备
    if (!base_device_->InitializeDevice()) {
        printf("初始化设备失败，请检查配置参数是否存在错误");
        return -1;
    }

    // 3.连接设备
    if (!base_device_->ConnectedDevice()) {
        printf("发送连接设备命令失败");
        return -1;
    }

    // 设备返回数据需要时间 1s后再判断
    std::this_thread::sleep_for(std::chrono::milliseconds(1000));
    if (!socket->is_initialized() || !socket->is_opened()){
        std::cout << "socket connect failed";
        return -1;
    }

    std::cout << "TCP设备连接成功!" << std::endl;

    // 4.下发采集配置

    // 采样率 1M
    auto legal_sample_rate = base_device_->GetADCLegalSampleRate();
    if (!base_device_->ConfigADCSampleRate(libdaq::device::LockzhinerADCSampleRate::ADCSampleRate_1_M)) {
        printf("采样率配置失败");
    }
    // 电压量程 1V
    if (!base_device_->ConfigADCVoltage(libdaq::device::LockzhinerADCVoltage::ADCVoltage_1_V)) {
        printf("电压量程配置失败");
    }
    
    // 根据设备类型配置通道数量
    int channel_count = base_device_->GetADCLegalChannelSize();
    uint8_t channel_mask = (1 << channel_count) - 1; // 生成对应通道数的掩码
    
    // 通道使能配置
    if (!base_device_->ConfigADCChannel(channel_mask)) {
        printf("ADC通道配置失败");
    }

    // 直流耦合配置
    if(!base_device_->ConfigACDC(channel_mask)){
        printf("ADC通道AC/DC配置失败");
    }

    // 触发电平 0mv
    uint32_t level=0;
    // 双边缘触发 单次采集 软件触发
    auto type = static_cast<libdaq::device::LockzhinerADCTriggerType>(libdaq::device::LockzhinerADCTriggerType::DoubleEdge);
    auto mode = static_cast<libdaq::device::LockzhinerADCTriggerMode>(libdaq::device::LockzhinerADCTriggerMode::Single);
    auto channel = static_cast<libdaq::device::LockzhinerADCChannel>(libdaq::device::LockzhinerADCChannel::ADCChannelAINNone);
    if (!base_device_->ConfigADCTrigger(type, mode, channel, level)) {
        printf("DAQ控制器配置ADC触发失败");
    }

    // 长度 4920个点
    if (!base_device_->ConfigADCTriggerLength(4920)) {
        printf("触发长度配置失败");
    }
    // 超时 100ms
    if (!base_device_->ConfigTriggerTimeout(100)) {
        printf("超时时间配置失败");
    }

    if(!base_device_->StopADCCollection()){
        printf("stop ADC采集失败\n");
        return -1;
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(50));

    // 开始采集
    if (!base_device_->StartADCCollection())
    {
        printf("启动ADC采集失败\n");
        return -1;
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    // 软件触发 单次触发需要下发该命令才会数据上来
    if (!base_device_->ConfigADCTriggerSource(static_cast<uint8_t>(libdaq::device::DAQADCTriggerSource::TriggerSourceSoftware)))
    {
        printf("软件触发失败");
        return -1;
    }


    // 创建线程读取数据
    int channel_number = base_device_->GetADCLegalChannelSize();
    std::vector<std::vector<float>> data(channel_number);
    std::vector<std::unique_ptr<OnceTriggerADCThread>> once_trigger_adc_thread(channel_number);
    for(int i = 0; i < channel_number; i++){
        once_trigger_adc_thread[i] = std::make_unique<OnceTriggerADCThread>(base_device_, i, data[i]);
        once_trigger_adc_thread[i]->start();
    }

    // 等待所有线程结束，而不只是第0个线程
    bool all_threads_finished = false;
    while (!all_threads_finished) {
        all_threads_finished = true;
        for(int i = 0; i < channel_number; i++) {
            if(once_trigger_adc_thread[i] && once_trigger_adc_thread[i]->thread_is_running()) {
                all_threads_finished = false;
                break;
            }
        }
        if (!all_threads_finished) {
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
        }
    }

    // 确保所有线程都正确退出
    for(int i = 0; i < channel_number; ++ i){
        if(once_trigger_adc_thread[i] != nullptr){
            once_trigger_adc_thread[i]->quit();
        }
    }

    return 0;
}
